/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package demo.reflection;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Scanner;

/**
 *
 * @author VANDH
 */
public class MainDemo {

    public static void examClass(Class c) {
        listFields(c);

        System.out.println("List of constructor ");
        System.out.println("---------------------------------------");


        // getConstructor return Constructor[]
        for (Constructor co : c.getConstructors()) {
            System.out.printf("%s%n", co.toGenericString());
        }

        listMethods(c);
    }

    private static void examMethod(Class c) throws NoSuchMethodException {
        // Lấy object Method từ tên và kiểu tham số
        String methodName = "max";
        Class p = int.class;

        Method m = c.getMethod(methodName, double.class, double.class);
        // m -> max(double, double)
        System.out.println(m.toGenericString());

        // Show thông tin method từ object Method đã có
        System.out.println(m.getName());
        Class[] paramters = m.getParameterTypes();

        for (Class i : paramters) {
            System.out.println(i.toString());
        }
    }

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        int choice;
        Scanner keyboard = new Scanner(System.in);

        do {
            System.out.println("1. Xem thông tin của một class");
            System.out.println("2. Xem thông tin của một hàm");
            System.out.println("3. Tạo object động, gọi hàm động");
            System.out.println("4. Tạo mảng động");
            System.out.println("0. Thoát");
            choice = keyboard.nextInt();

            switch (choice) {
                case 1:
                    // java.lang.Math
                    System.out.printf("Enter class name : ");
                    String className = keyboard.next();
                    Class c = Class.forName(className);
                    examClass(c);
                    break;
                case 2:
                    System.out.printf("Enter class name : ");
                    className = keyboard.next();
                    c = Class.forName(className);
                    examMethod(c);
                    break;
                case 3:
                    createObject();
                    break;
                case 4:
                    createArray();
                    break;
            }
        } while (choice != 0);
    }

    private static void listFields(Class c) throws SecurityException {
        System.out.println("List of fields ");
        System.out.println("---------------------------------------");

        for (Field f : c.getFields()) {
            System.out.printf("%s%n", f.toGenericString());
        }
    }

    private static void listMethods(Class c) throws SecurityException {
        System.out.println("List of methods ");
        System.out.println("---------------------------------------");


        // getMethods return Method[]
        for (Method m : c.getMethods()) {
            System.out.printf("%s%n", m.toGenericString());
        }
    }

    private static void createObject() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
        // Tạo object động
        String className = "java.lang.String";
        Class c = Class.forName(className);


        // c là Class chứa thông tin class "java.lang.String"
        // dùng c.newInstance() để tạo ra object bằng
        // constructor mặc định
        //Object s = c.newInstance(); // new String()
        Constructor co = c.getConstructor(String.class);    // new String("abc");
        Object s = co.newInstance("abc");   // new String("abc")

        System.out.println(s);
        if (s instanceof String) {
            System.out.println("String");
        } else {
            System.out.println("Not string");
        }

        // gọi phương thức indexOf của String
        Method m = c.getMethod("indexOf", String.class);
        Integer i = (Integer) m.invoke(s, "d");
        System.out.println(i);
    }

    private static void createArray() throws ClassNotFoundException {
        int count = 3;
        String className = "java.lang.String";
        Class c = Class.forName(className);

        Object ar = Array.newInstance(c, count);

        Array.set(ar, 0, "abc");
        Array.set(ar, 1, "def");
        Array.set(ar, 2, "ghi");

        for (int i = 0; i < Array.getLength(ar); i++) {
            System.out.println(Array.get(ar, i));
        }
        // infernocorez@gmail.com
    }
}
